
//OS
#include "jxos_public.h"

//LIB
#include "lib\bit.h"

//SYS TASK
#include "jsnet_phy.h"


void (*jsnet_phy_confirm_data_send)(uint8_t ok_fail) = 0;
void (*jsnet_phy_indication_data_receive)(uint8_t* receive_data, uint8_t data_len) = 0;

static uint8_t (*jsnet_phy_request_check_tx_busy_callback)(void) = 0;
static uint8_t (*jsnet_phy_request_rx_disable_callback)(void) = 0;
static uint8_t (*jsnet_phy_request_tx_disable_callback)(void) = 0;
static uint8_t (*jsnet_phy_request_rx_enable_callback)(void) = 0;
static uint8_t (*jsnet_phy_request_tx_enable_callback)(void) = 0;
static uint8_t (*jsnet_phy_request_data_send_callback)(uint8_t* send_data, uint8_t data_len) = 0;

#define RXEN_FLAG				0
#define TXEN_FLAG				1
#define SEND_FAIL_FALG          6
#define IDLE_ASSM			    7
static uint8_t phy_task_flag = 0;

static JXOS_EVENT_HANDLE PHY_SEND_EVENT;
static JXOS_EVENT_HANDLE PHY_SEND_OK_EVENT;
static JXOS_EVENT_HANDLE PHY_RECEIVE_OK_EVENT;

static swtime_type SEND_OVERTIME_TIMER;
static swtime_type SEND_RETRY_TIMER;

static uint8_t receive_data_buffer[JXNET_PHY_REC_BYFF_LEN];
static uint8_t volatile receive_data_len = 0;
static uint8_t send_data_buffer[JXNET_PHY_SEND_BYFF_LEN];
static uint8_t volatile send_data_len = 0;
static uint8_t volatile send_retry_counter = 0;

static void phy_task(uint8_t task_id, void * parameter)
{
	if((jxos_event_wait(PHY_SEND_EVENT) == 1)
    ||(sys_svc_software_timer_check_overtime(SEND_RETRY_TIMER) == 1)){
        sys_svc_software_timer_stop(SEND_RETRY_TIMER);
        if(jsnet_phy_request_check_tx_busy() == 0){
	        if(jsnet_phy_request_data_send_callback != 0){
                if(jsnet_phy_request_data_send_callback(send_data_buffer, send_data_len) == 1){
                    sys_svc_software_timer_set_time(SEND_OVERTIME_TIMER, JXNET_PHY_SEND_OVERTIME_TIME_MS);
                    sys_svc_software_timer_restart(SEND_OVERTIME_TIMER);
                }
                else{
                    set_bit(phy_task_flag, SEND_FAIL_FALG);
                }
            }
            else{
                set_bit(phy_task_flag, SEND_FAIL_FALG);
            }
        }
        else{
            if(send_retry_counter < JXNET_PHY_SEND_RETRY_COUNT){
                send_retry_counter++;
                sys_svc_software_timer_set_time(SEND_RETRY_TIMER, JXNET_PHY_SEND_RETRY_TIME_MS);
                sys_svc_software_timer_restart(SEND_RETRY_TIMER);
            }
            else{
                set_bit(phy_task_flag, SEND_FAIL_FALG);
            }
        }
	}

    if((sys_svc_software_timer_check_overtime(SEND_OVERTIME_TIMER) == 1)
    ||(get_bit(phy_task_flag, SEND_FAIL_FALG) == 1)){
        reset_bit(phy_task_flag, SEND_FAIL_FALG);
        sys_svc_software_timer_stop(SEND_OVERTIME_TIMER);
		if(jsnet_phy_confirm_data_send != 0)
			jsnet_phy_confirm_data_send(0);
    }

	if(jxos_event_wait(PHY_SEND_OK_EVENT) == 1){
		sys_svc_software_timer_stop(SEND_OVERTIME_TIMER);
		if(jsnet_phy_confirm_data_send != 0)
			jsnet_phy_confirm_data_send(1);
	}

	if(jxos_event_wait(PHY_RECEIVE_OK_EVENT) == 1){
		printf("phy receive_data_len %d\r\n", receive_data_len);
		if(jsnet_phy_indication_data_receive != 0)
			jsnet_phy_indication_data_receive(receive_data_buffer, receive_data_len);
	}
}

void phy_task_init(void)
{
	//OS
	jxos_task_create(phy_task, "jn_phy", 0);

    PHY_SEND_EVENT = jxos_event_create();
	PHY_SEND_OK_EVENT = jxos_event_create();
	PHY_RECEIVE_OK_EVENT = jxos_event_create();

    SEND_OVERTIME_TIMER = sys_svc_software_timer_new();
    SEND_RETRY_TIMER = sys_svc_software_timer_new();

	jsnet_phy_request_rx_disable();
	jsnet_phy_request_tx_disable();
}

void phy_data_send_finish_handler(void)
{
	jxos_event_set(PHY_SEND_OK_EVENT);
}

void phy_data_receive_handler(uint8_t* receive_data, uint8_t data_len)
{
	if((data_len > JXNET_PHY_REC_BYFF_LEN)
    ||(receive_data == 0)){
        return;
	}

	printf("phy_data_receive_handler\r\n");
	if(get_bit(phy_task_flag, RXEN_FLAG) == 1){
        jxos_event_set(PHY_RECEIVE_OK_EVENT);
        memcpy(receive_data_buffer, receive_data, data_len);
        receive_data_len = data_len;
	}
}

void phy_check_tx_busy_callback_register(uint8_t (*callback_handler)(void))
{
    if(callback_handler != 0){
        jsnet_phy_request_check_tx_busy_callback = callback_handler;
    }
}

void phy_rx_disable_callback_register(uint8_t (*callback_handler)(void))
{
    if(callback_handler != 0){
        jsnet_phy_request_rx_disable_callback = callback_handler;
    }
}

void phy_tx_disable_callback_register(uint8_t (*callback_handler)(void))
{
    if(callback_handler != 0){
        jsnet_phy_request_tx_disable_callback = callback_handler;
    }
}

void phy_rx_enable_callback_register(uint8_t (*callback_handler)(void))
{
    if(callback_handler != 0){
        jsnet_phy_request_rx_enable_callback = callback_handler;
    }
}

void phy_tx_enable_callback_register(uint8_t (*callback_handler)(void))
{
    if(callback_handler != 0){
        jsnet_phy_request_tx_enable_callback = callback_handler;
    }
}

void phy_data_send_callback_register(uint8_t (*callback_handler)(uint8_t* send_data, uint8_t data_len))
{
    if(callback_handler != 0){
        jsnet_phy_request_data_send_callback = callback_handler;
    }
}

/************************************************************/
uint8_t jsnet_phy_request_check_tx_busy(void)
{
    if(jsnet_phy_request_check_tx_busy_callback != 0){
        return jsnet_phy_request_check_tx_busy_callback();
    }
    else{
        return 0;
    }
}

uint8_t jsnet_phy_request_rx_disable(void)
{
    if(jsnet_phy_request_rx_disable_callback != 0){
        if(jsnet_phy_request_rx_disable_callback() == 1){
//            reset_bit(phy_task_flag, RXEN_FLAG);
            return 1;
        }
    }
    return 0;
}

uint8_t jsnet_phy_request_tx_disable(void)
{
    if(jsnet_phy_request_tx_disable_callback != 0){
        if(jsnet_phy_request_rx_disable_callback() == 1){
            reset_bit(phy_task_flag, TXEN_FLAG);
            return 1;
        }
    }
    return 0;
}

uint8_t jsnet_phy_request_rx_enable(void)
{
    if(jsnet_phy_request_rx_enable_callback != 0){
        if(jsnet_phy_request_rx_enable_callback() == 1){
            set_bit(phy_task_flag, RXEN_FLAG);
            return 1;
        }
    }
    return 0;
}

uint8_t jsnet_phy_request_tx_enable(void)
{
    if(jsnet_phy_request_tx_enable_callback != 0){
        if(jsnet_phy_request_tx_enable_callback() == 1){
            set_bit(phy_task_flag, TXEN_FLAG);
            return 1;
        }
    }
    return 0;
}

uint8_t jsnet_phy_request_reset(void)
{
	if(jsnet_phy_request_rx_disable() != 1){
        return 0;
	}
	if(jsnet_phy_request_tx_disable() != 1){
        return 0;
	}
	jxos_event_wait(PHY_SEND_OK_EVENT);
	jxos_event_wait(PHY_RECEIVE_OK_EVENT);
	return 1;
}

uint8_t jsnet_phy_request_data_send(uint8_t* send_data, uint8_t data_len)
{
	if((data_len > JXNET_PHY_SEND_BYFF_LEN)
    ||(send_data == 0)){
        return 0;
	}

	if(get_bit(phy_task_flag, TXEN_FLAG) == 1){
        jxos_event_set(PHY_SEND_EVENT);
        memcpy(send_data_buffer, send_data, data_len);
        send_data_len = data_len;
        send_retry_counter = 0;
        return 1;
	}
    return 0;
}

//uint8_t jsnet_phy_request_channel_idle_assessment(void)
//{
//	set_bit(phy_task_flag, RF_IDLE_ASSM);
//	return get_bit(phy_task_flag, RXEN_FLAG);
//}

//void (*jsnet_phy_confirm_channel_idle_assessment)(uint8_t idle_busy);


